
var needs_init = true;
var preset = -1; // VISUAL_PARAM_LIMIT_INTEGER(-1, 7), "Preset choice"),
var subpixel = 1; // VISUAL_PARAM_LIMIT_NONE, ""),
var rectcoords = 1; // VISUAL_PARAM_LIMIT_BOOLEAN, "Rectangular coordinates"),
var xres = 20; // VISUAL_PARAM_LIMIT_INTEGER(2, 256), "Grid size x axis"),
var yres = 20; // VISUAL_PARAM_LIMIT_INTEGER(2, 256), "Grid size y axis"),
var blend = 1; // VISUAL_PARAM_LIMIT_BOOLEAN, "Blend"),
var wrap = 1; // VISUAL_PARAM_LIMIT_BOOLEAN, "Wrap"),
var buffern = 0; // VISUAL_PARAM_LIMIT_INTEGER(0, 8), "Source buffer"),
var nomove = 0; // VISUAL_PARAM_LIMIT_BOOLEAN, "No movement (just blend)"),

var d; //d);
var b; //b);
var r; //r);
var x; //x);
var y; //y);
var w; //w);
var h; //h);
var alpha; //alpha);

function init = ""  //Set intial variable values here
function frame = ""; // Used to define movement and transformations
function beat = ""; // Expression that gets evaluated on the beat
function pixel = ""; //This is where the shape is defined


function trans_begin(priv, isBeat, fbin, fbout)
{
    printf("trans_begin\n");
    var thread = 0;
    var max_threads = 1;

    priv.__subpixel = priv.subpixel;
    priv.__rectcoords = priv.rectcoords;
    priv.__blend = priv.blend;
    priv.__wrap = priv.wrap;
    priv.__nomove = priv.nomove;

    priv.w_adj = (priv.width - 2)<<16;
    priv.h_adj = (priv.height - 2)<<16;
    
    if(priv.xres < 2) priv.xres = 2;
    if(priv.xres > 256) priv.xres = 256;
    if(priv.yres < 2) priv.yres = 2;
    if(priv.yres > 256) priv.yres = 256;
    
    if(priv.last_xres != priv.xres || priv.last_yres != priv.yres || 
            priv.last_width != priv.width || priv.last_height != priv.height || 
            !priv.tab || !priv.wmul ) {
        var y;
        priv.last_xres = priv.xres;
        priv.last_yres = priv.yres;
        priv.last_width = priv.width;
        priv.last_height = priv.height;

        if(priv.wmul != NULL) 
            visual_mem_free(priv.wmul);
        priv.wmul = visual_mem_malloc0(priv.height);

        for(y = 0; y < priv.height; y++) 
            priv.wmul[y] = y * priv.width;

        if(priv.tab != NULL)
            visual_mem_free(priv.tab);

        priv.tab = visual_mem_malloc0((priv.xres * priv.yres * 3 + (priv.xres * 6 + 6)*max_threads) * sizeof(int));
    }

    if(!priv.__subpixel)
    {
        priv.w_adj = (priv.width-1)<<16;
        priv.w_adj = (priv.height-1)<<16;
    }

    if(isBeat&0x80000000)
        return;

    priv.var_w = (AvsNumber)priv.width;
    priv.var_h = (AvsNumber)priv.height;
    priv.var_b = isBeat?1.0:0.0;
    priv.var_alpha = 0.5;

    if(priv.needs_init) {
        priv.needs_init = FALSE;
        trans_run_runnable(priv, TRANS_RUNNABLE_INIT);
    }
    // execute code
    trans_run_runnable(priv, TRANS_RUNNABLE_FRAME);

    if(isBeat)
        trans_run_runnable(priv, TRANS_RUNNABLE_BEAT);

    {
        int32_t x, y;
        var tabptr=priv.tabptr;

        var xsc = 2.0/priv.width, ysc=2.0/priv.height;
        var dw2 = (priv.width*32768.0);
        var dh2 = (priv.height*32768.0);
        var max_screen_d = sqrt((priv.width*priv.width + priv.height*priv.height)) * 0.5;

        var divmax_d = 1.0/max_screen_d;

        var yc_pos, yc_dpos, xc_pos, xc_dpos;

        max_screen_d *= 65536.0;

        yc_pos = 0;
        xc_dpos = (priv.width << 16)/(priv.xres-1);
        yc_dpos = (priv.height << 16)/(priv.yres-1);
        for(y = 0; y < priv.yres; y++) 
        {
            xc_pos = 0;
            for(x = 0; x < priv.xres; x++)
            {
                var xd, yd;
                var tmp1, tmp2;
                var va;
                var a;

                xd = (xc_pos-dw2)*(1.0/65536.0);
                yd = (yc_pos-dh2)*(1.0/65536.0);

                xc_pos+=xc_dpos;

                priv.var_x = xd*xsc;
                priv.var_y = yd*ysc;
                priv.var_d = sqrt(xd*xd + yd*yd)*divmax_d;
                priv.var_r = atan2(yd, xd) + PI*0.5;

		pixel();

                if(!priv.__rectcoords)
                {
                    priv.var_d *= max_screen_d;
                    priv.var_r -= PI*0.5;
                    tmp1 = floor(dw2 + cos(priv.var_r) * priv.var_d);
                    tmp2 = floor(dh2 + sin(priv.var_r) * priv.var_d);
                }
                else
                {
                    tmp1 = floor((priv.var_x+1.0)*dw2);
                    tmp2 = floor((priv.var_y+1.0)*dh2);
                }
                if(!priv.__wrap)
                {
                    if(tmp1 < 0)            tmp1 = 0;
                    if(tmp1 > priv.w_adj)  tmp1 = priv.w_adj;
                    if(tmp2 < 0)            tmp2 = 0;
                    if(tmp2 > priv.h_adj)  tmp2 = priv.h_adj;
                }   

		tab[tabptr++] = tmp1;
		tab[tabptr++] = tmp2;
                va = priv.var_alpha;
                if(va < 0.0) 
                    va = 0.0;
                else if (va > 1.0)
                    va = 1.0;
                a = floor(va*255.0*65536.0);
                tabptr++ = a;
            }
            yc_pos+=yc_dpos;
        }
    }
}

function trans_render(priv, isBeat, fb, fbout)
{
    int max_threads = 1;
    int this_thread = 0;

    int start_l = (this_thread * priv.height) / max_threads;
    int end_l;
    int ypos = 0;

    if(this_thread >= max_threads - 1) end_l = priv.height;
    else end_l = ((this_thread+1) * priv.height) / max_threads;

    int outh = end_l-start_l;
    if(outh<1) return;

    uint32_t *fbin = !priv.buffern ? fb : 
        (uint32_t *)avs_get_global_buffer(priv.proxy, priv.width, priv.height, priv.buffern-1, 0).buffer;

    printf("buffern = %d\n", priv.buffern);
    {
        uint32_t *interptab = priv.tab + priv.xres * priv.yres * 3 + this_thread * (priv.xres * 6 + 6);
        uint32_t *rdtab = priv.tab;
        unsigned int *in = (unsigned int *)fbin;
        unsigned int *blendin = (unsigned int *)fb;
        unsigned int *out = (unsigned int *)fbout;
        int yseek = 1;
        int xc_dpos, yc_pos=0, yc_dpos;
        xc_dpos = (priv.width<<16)/(priv.xres-1);
        yc_dpos = (priv.height<<16)/(priv.yres-1);
        int lypos = 0;
        int yl = end_l;
        while(yl>0)
        {
            yc_pos+=yc_dpos;
            yseek=(yc_pos>>16)-lypos;
            if( !yseek ) 
            {
                #ifdef HAS_MMX
                    //__asm emms;
                #endif
                return;
            }
            lypos = yc_pos >> 16;
            int l = priv.xres;
            uint32_t *stab = interptab;
            int xr3=priv.xres * 3;
            while(l--)
            {
                int tmp1, tmp2, tmp3;
                tmp1 = rdtab[0];
                tmp2 = rdtab[1];
                tmp3 = rdtab[2];
                stab[0] = tmp1;
                stab[1] = tmp2;
                stab[2] = (rdtab[xr3]-tmp1)/yseek;
                stab[3] = (rdtab[xr3+1]-tmp2)/yseek;
                stab[4] = tmp3;
                stab[5] = (rdtab[xr3+2]-tmp3)/yseek;
                rdtab+=3;
                stab+=6;
            }

            if(yseek > yl) yseek = yl;
            yl-=yseek;

            if(yseek > 0) while(yseek--)
            {
                int d_x;
                int d_y;
                int d_a;
                int ap;
                int seek;
                uint32_t *seektab = interptab;
                int xp,yp;
                int l = priv.width;
                int lpos = 0;
                int xc_pos = 0;
                ypos++;
                {
                    while(l>0)
                    {
                        xc_pos+=xc_dpos;
                        seek = (xc_pos>>16)-lpos;
                        if(!seek)
                        {
                            #ifdef HAS_MMX
                                //__asm emms;
                            #endif
                            return;
                        }
                        lpos = xc_pos >> 16;
                        xp = seektab[0];
                        yp = seektab[1];
                        ap = seektab[4];
                        d_a = (seektab[10]-ap)/seek;
                        d_x = (seektab[6]-xp)/seek;
                        d_y = (seektab[7]-yp)/seek;
                        seektab[0] += seektab[2];
                        seektab[1] += seektab[3];
                        seektab[4] += seektab[5];
                        seektab += 6;

                        if(seek > l) 
                            seek = l;

                        l -= seek;
                        if(seek > 0 && ypos <= start_l)
                        {
                            blendin+=seek;
                            if(priv.__nomove) in+=seek;
                            else out+=seek;

                            seek = 0;
                        }

                        if (seek > 0)
                        {
#define CHECK
#define NORMAL_LOOP(Z) while ((seek--)) { Z; xp+=d_x; yp+=d_y; }

#define WRAPPING_LOOPS(Z) \
    NORMAL_LOOP(if (xp < 0) xp += priv.w_adj;  \
                else if (xp >= priv.w_adj) xp-=priv.w_adj;  \
                if (yp < 0) yp += priv.h_adj;  \
                else if (yp >= priv.h_adj) yp-=priv.h_adj;  \
                Z)

#define CLAMPED_LOOPS(Z) \
    NORMAL_LOOP(if (xp < 0) xp=0; \
                else if (xp >= priv.w_adj) xp=priv.w_adj-1; \
                if (yp < 0) yp=0; \
                else if (yp >= priv.h_adj) yp=priv.h_adj-1; \
                Z)

#define LOOPS(DO)  \
                if (priv.__blend && priv.__subpixel) DO(CHECK *out++=BLEND_ADJ(priv.proxy, BLEND4_16(priv.proxy, in+(xp>>16)+(priv.wmul[yp>>16]),priv.width,xp,yp),*blendin++,ap>>16); ap+=d_a) \
                else if (priv.__blend) DO(CHECK *out++=BLEND_ADJ(priv.proxy, in[(xp>>16)+(priv.wmul[yp>>16])],*blendin++,ap>>16); ap+=d_a) \
                else if (priv.__subpixel) DO(CHECK *out++=BLEND4_16(priv.proxy, in+(xp>>16)+(priv.wmul[yp>>16]),priv.width,xp,yp)) \
                else DO(CHECK *out++=in[(xp>>16)+(priv.wmul[yp>>16])])

                            if(priv.__nomove)
                            {
                                if(fbin != fb) while(seek--)
                                {
                                    *blendin=BLEND_ADJ(priv.proxy, *in++, *blendin, ap>>16);
                                    ap+=d_a;
                                    blendin++;
                                }
                                else while( seek--)
                                {
                                    *blendin=BLEND_ADJ(priv.proxy, 0, *blendin, ap>>16);
                                    ap+=d_a;
                                    blendin++;
                                }
                            }
                            else if (!priv.__wrap)
                            {
                                if(xp < 0) xp = 0;
                                else if (xp >= priv.w_adj) xp=priv.w_adj-1;
                                if(yp < 0) yp = 0;
                                else if (yp >= priv.h_adj) yp=priv.h_adj-1;

                                LOOPS(CLAMPED_LOOPS)
                            }
                            else
                            {
                                xp %= priv.w_adj;
                                yp %= priv.h_adj;
                                if(xp < 0) xp+=priv.w_adj;
                                if(yp < 0) yp+=priv.h_adj;

                                if(d_x <= -priv.w_adj) d_x = -priv.w_adj + 1;
                                else if (d_x >= priv.w_adj) d_x = priv.w_adj - 1;

                                if(d_y <= -priv.h_adj) d_y = -priv.h_adj + 1;
                                else if (d_y >= priv.h_adj) d_y = priv.h_adj - 1;

                                LOOPS(WRAPPING_LOOPS)
                            }
                        } // if seek>0
                    }
                    seektab[0] += seektab[2];
                    seektab[1] += seektab[3];
                    seektab[4] += seektab[5];
                }
            }
        }
    }
}



